#ifndef YAEE_reflection_TRANSFORM_H__
#define YAEE_reflection_TRANSFORM_H__

#include "tbcore/predefined.hpp"
#include "../base/string/string_util.hpp"

#include "type_traits.hpp"
#include "reflection_export.hpp"

TB_NAMESPACE_BEGIN

TB_REFLECTION_API _STD string BuildinTypeToString(const Variant* val);

class Transform {};

template <typename T, typename Enabled = void>
struct is_transform
  : false_type {};

template <typename T> struct
is_transform<T, typename enable_if<check_method<void (T::*)(const reflection::TypeInfo*, uint32), &T::Begin>::value >::type >
: true_type{};

template <class Transform> 
void Apply(const Variant& val, Transform& trans) {
  BOOST_STATIC_ASSERT(is_transform<Transform>::value);
  uint32 id = val.TypeId();
  if (const reflection::TypeInfo* info = reflection::GetTypeInfo(id)) {
    const std::vector<const reflection::Property*>& properties
      = reflection::GetProperties(id);
    trans.Begin(info, (uint32)properties.size());
    for (size_t i = 0; i < info->properties.size(); ++i) {
      const reflection::Property* prop = boost::addressof(info->properties.at(i));
      Variant pval = prop->Get(val.DataPtr());
      trans.Field(prop, &pval);
    }
    trans.End();
  }
}

class TB_REFLECTION_API PrettyStringifyTransform : Transform {
 public:
  PrettyStringifyTransform();
  ~PrettyStringifyTransform();
  _STD string Stringify(const Variant* val);
 private:
  friend void Apply<PrettyStringifyTransform>(const Variant&, PrettyStringifyTransform&);
  void Begin(const reflection::TypeInfo* info, uint32);
  void Field(const reflection::Property* prop, const Variant* val);
  void End();
 private:
  struct PrettyStringifyTransformImpl;
  PrettyStringifyTransformImpl* impl_;
};

TB_NAMESPACE_END

#endif // YAEE_reflection_TRANSFORM_H__
